package utils

import (
	"context"
	"fmt"
	"os"
	"os/exec"
	"path/filepath"
	"strings"
	"time"

	"bsm/logger"
)

type ExcelPdfConverterLibre struct {
	semaphore       chan struct{}
	tempDir         string
	libreOfficePath string
}

func NewExcelPdfConverterLibre(maxConcurrent int) (*ExcelPdfConverterLibre, error) {
	libreOfficePath := os.Getenv("LIBREOFFICE_PATH")
	if libreOfficePath == "" {
		logger.WithFields(map[string]interface{}{
			"layer":     "utils",
			"operation": "NewExcelPdfConverterLibre",
		}).Error("未找到LibreOffice安装路径，请设置LIBREOFFICE_PATH环境变量或确保LibreOffice已安装")
		return nil, fmt.Errorf("未找到LibreOffice安装路径，请设置LIBREOFFICE_PATH环境变量或确保LibreOffice已安装")
	}

	// 2. 验证LibreOffice是否可执行
	// if err := verifyLibreOffice(libreOfficePath); err != nil {
	// 	return nil, fmt.Errorf("LibreOffice验证失败: %v", err)
	// }

	// 3. 创建临时目录
	tempDir := filepath.Join(os.TempDir(), "excel_pdf_converter")
	if err := os.MkdirAll(tempDir, 0755); err != nil {
		logger.WithFields(map[string]interface{}{
			"layer":     "utils",
			"operation": "NewExcelPdfConverterLibre",
			"error":     err.Error(),
		}).Error("创建临时目录失败")
		return nil, fmt.Errorf("创建临时目录失败: %v", err)
	}

	return &ExcelPdfConverterLibre{
		semaphore:       make(chan struct{}, maxConcurrent),
		tempDir:         tempDir,
		libreOfficePath: libreOfficePath,
	}, nil
}

// 验证LibreOffice功能
// func verifyLibreOffice(path string) error {
// 	cmd := exec.Command(path, "--version")
// 	_, err := cmd.CombinedOutput()
// 	return err
// }

func (s *ExcelPdfConverterLibre) ConvertExcelToPDF(excelPath string) (string, error) {
	// 1. 验证输入文件是否存在
	if _, err := os.Stat(excelPath); os.IsNotExist(err) {
		logger.WithFields(map[string]interface{}{
			"layer":     "utils",
			"operation": "ConvertExcelToPDF",
			"error":     err.Error(),
		}).Error("excel文件不存在")
		return "", fmt.Errorf("excel文件不存在: %s", excelPath)
	}

	// 2. 获取并发许可（带超时）
	select {
	case s.semaphore <- struct{}{}:
		defer func() { <-s.semaphore }()
	case <-time.After(30 * time.Second): // 增加超时时间
		return "", fmt.Errorf("系统繁忙，请稍后重试")
	}

	// 3. 生成唯一PDF文件名（基于输入文件名）
	baseName := filepath.Base(excelPath)
	ext := filepath.Ext(baseName)
	// pdfName := strings.TrimSuffix(baseName, ext) + ".pdf"
	pdfPath := filepath.Join(s.tempDir, fmt.Sprintf("%s_%d.pdf",
		strings.TrimSuffix(baseName, ext), time.Now().UnixNano()))

	// 4. 创建唯一配置目录
	uniqueDir := filepath.Join(s.tempDir, "profile_"+fmt.Sprintf("%d", time.Now().UnixNano()))
	if err := os.MkdirAll(uniqueDir, 0755); err != nil {
		logger.WithFields(map[string]interface{}{
			"layer":     "utils",
			"operation": "ConvertExcelToPDF",
			"error":     err.Error(),
		}).Error("创建配置目录失败")
		return "", fmt.Errorf("创建配置目录失败: %v", err)
	}
	defer os.RemoveAll(uniqueDir)

	// 5. 构建命令行参数（处理Windows路径）
	args := []string{
		"--headless",
		"--convert-to", "pdf:calc_pdf_Export", // 使用Calc专用的PDF导出过滤器
		"--outdir", s.tempDir,
		excelPath,
	}

	// 6. 执行转换（带超时控制）
	// cmd := exec.Command(s.libreOfficePath, args...)

	// 设置超时上下文
	ctx, cancel := context.WithTimeout(context.Background(), 2*time.Minute)
	defer cancel()

	// 使用CommandContext支持超时
	cmd := exec.CommandContext(ctx, s.libreOfficePath, args...)

	output, err := cmd.CombinedOutput()
	if err != nil {
		if ctx.Err() == context.DeadlineExceeded {
			logger.WithFields(map[string]interface{}{
				"layer":     "utils",
				"operation": "ConvertExcelToPDF",
				"error":     ctx.Err().Error(),
			}).Error("PDF转换超时")
			return "", fmt.Errorf("PDF转换超时")
		}
		return "", fmt.Errorf("PDF转换失败: %v, 输出: %s", err, string(output))
	}

	// 7. 验证生成的PDF文件
	if _, err := os.Stat(pdfPath); os.IsNotExist(err) {
		// 尝试查找LibreOffice可能生成的其他名称的PDF文件
		if altPath := s.findGeneratedPDF(excelPath); altPath != "" {
			return altPath, nil
		}
		logger.WithFields(map[string]interface{}{
			"layer":     "utils",
			"operation": "ConvertExcelToPDF",
			"error":     fmt.Sprintf("PDF文件未生成，LibreOffice输出: %s", string(output)),
		}).Error("PDF文件未生成")
		return "", fmt.Errorf("PDF文件未生成，LibreOffice输出: %s", string(output))
	}

	return pdfPath, nil
}

// 查找LibreOffice生成的PDF文件（处理命名差异）
func (s *ExcelPdfConverterLibre) findGeneratedPDF(excelPath string) string {
	baseName := filepath.Base(excelPath)
	pdfPattern := strings.TrimSuffix(baseName, filepath.Ext(baseName)) + "*.pdf"

	matches, err := filepath.Glob(filepath.Join(s.tempDir, pdfPattern))
	if err != nil || len(matches) == 0 {
		return ""
	}
	return matches[0]
}

// 清理临时文件的方法
func (s *ExcelPdfConverterLibre) Cleanup() error {
	return os.RemoveAll(s.tempDir)
}

// 获取当前并发任务数
func (s *ExcelPdfConverterLibre) GetActiveTasks() int {
	return len(s.semaphore)
}
